/*该代码模拟实现了FILE, fopen, fclose, fputs*/
//注意一下命名规范，最好有自己的一套命名方法
//宏：全大写
//变量名：小写 + 下划线
//函数名：首字母大写，如Getsum,Lca
//类名：帕斯卡命名法（所有单词首字母大写）


#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define NUM 1024

struct myFILE
{
  int fd;
  char* buffer[NUM];//缓冲区
  int end;//标记光标在缓冲区的位置
};

typedef struct myFILE myFILE;

myFILE* fopen_(const char* filename, const char* mode)
{
 assert(filename && mode);

  myFILE* fp = (myFILE*)malloc(sizeof(myFILE));
 // if (fp == NULL)
 // {
 //   perror("malloc");
 //   return fp;
 // }
 
  if (fp)//!= NULL
  {
    if (strcmp("w", mode) == 0)
    {
      fp->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    } 
    else if (strcmp("w+", mode) == 0)
    {
      //open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    } 
    else if (strcmp("r", mode) == 0)
    {
      fp->fd = open(filename, O_RDONLY);
    } 
    else if (strcmp("r+", mode) == 0)
    {
      //open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    } 
    else if (strcmp("a", mode) == 0)
    {
      fp->fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666);
    } 
    else if (strcmp("a+", mode) == 0)
    {
      //open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    }
    else
    {

    }

    if (fp->fd < 0)
    {
      exit(1);
    }

  }

  return fp;
}

void fflush_(myFILE* fp)
{
   assert(fp);

  if (fp->end != 0)
  {
     /*
      *#include <unistd.h>

      ssize_t write(int fd, const void *buf, size_t count);

     */


    write(fp->fd, fp->buffer, fp->end);//把内容写到了内核，还并没有写入文件（磁盘）
    syncfs(fp->fd);//内容写到磁盘
    fp->end = 0;
  }
}

void fputs_(const char* s, myFILE* fp)
{//fputs( const char *__restrict __s, FILE *__restrict __stream )          f int 
  assert(s && fp);

  //将数据放入缓冲区
  strcpy(fp->buffer + fp->end, s);
  fp->end += strlen(s);

  printf("%s\n", fp->buffer);

  if (fp->fd == 0)
  {

  }
  else if (fp->fd == 1)
  {
    //标准输出
    //显示器
    //行刷新
    
    if (fp->buffer + fp->end == '\n')
      fflush_(fp);
  }
  else if (fp->fd == 2)
  {
    //标准错误
  }
  else
  {
    //普通文件
  }
}

void fclose_(myFILE* fp)
{
  assert(fp);
  fflush_(fp);
  close(fp->fd);
  free(fp);
}

int main()
{
  //close(1);
  myFILE* fp = fopen_("log.txt", "w");
  if (fp == NULL)
    return 1;
  //fp->fd = 1;
  fputs_("hello myFILE", fp);
  fputs_("hello myFILE\n", fp);
  fputs_("hello myFILE", fp);
  fputs_("hello myFILE", fp);
  fputs_("hello myFILE", fp);

  fclose_(fp);
  return 0;
}
